package org.fuyd.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 二维码相关的的工具类
 * 
 * @author 永德
 *
 */
public final class QRCodeUtil {

  private static final int BLACK = 0xFF000000;
  private static final int WHITE = 0xFFFFFFFF;

  /**
   * 创建二维码的输入流
   * 
   * @param info
   * @param width
   * @param height
   * @return
   * @throws WriterException
   * @throws ImageFormatException
   * @throws IOException
   */
  public static InputStream createInputStream(String info, int width, int height)
      throws WriterException, ImageFormatException, IOException {
    MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
    Map<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

    BitMatrix bitMatrix =
        multiFormatWriter.encode(info, BarcodeFormat.QR_CODE, width, height, hints);

    BufferedImage bufferedImage = toBufferedImage(bitMatrix);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(bos);
    jpeg.encode(bufferedImage);
    byte[] bts = bos.toByteArray();
    InputStream inputStream = new ByteArrayInputStream(bts);

    return inputStream;
  }

  /**
   * 生成二维码信息的BufferedImage
   * 
   * @param bitMatrix
   * @return
   */
  public static BufferedImage toBufferedImage(BitMatrix bitMatrix) {
    int width = bitMatrix.getWidth();
    int height = bitMatrix.getHeight();
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
      }
    }
    return image;
  }

  /**
   * 将二维码信息写入到文件
   * 
   * @param bitMatrix
   * @param format
   * @param file
   * @throws IOException
   */
  public static void writeToFile(BitMatrix bitMatrix, String format, File file) throws IOException {
    BufferedImage image = toBufferedImage(bitMatrix);
    if (!ImageIO.write(image, format, file)) {
      throw new IOException("Could not write an image of format " + format + " to " + file);
    }
  }

  /**
   * 将二维码信息写入到OutputStream
   * 
   * @param bitMatrix
   * @param format
   * @param stream
   * @throws IOException
   */
  public static void writeToStream(BitMatrix bitMatrix, String format, OutputStream stream)
      throws IOException {
    BufferedImage image = toBufferedImage(bitMatrix);
    if (!ImageIO.write(image, format, stream)) {
      throw new IOException("Could not write an image of format " + format);
    }
  }

}
